package com.example.demo.config;

import com.example.demo.Util.AiUtil;
import dev.langchain4j.community.store.embedding.redis.RedisEmbeddingStore;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.ClassPathDocumentLoader;
import dev.langchain4j.mcp.McpToolProvider;
import dev.langchain4j.mcp.client.DefaultMcpClient;
import dev.langchain4j.mcp.client.McpClient;
import dev.langchain4j.mcp.client.transport.McpTransport;
import dev.langchain4j.mcp.client.transport.http.HttpMcpTransport;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.spring.AiService;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;

@Configuration
public class AiConfig {
    @Value("${BAIDU_API}")
    private  String BAIDU_API_KEY;    //配置RedisEmbeddingStore,做对话记录持久化
    @Autowired
    private RedisChatMemoryStore redisChatMemoryStore;
    //配置RedisEmbeddingStore,做向量数据库持久化
    @Autowired
    private RedisEmbeddingStore redisEmbeddingStore;
    @Value("${Ai.apiKey}")
    private String AIKEY;
    @Value("${Ui.url}")
    private String AIURL;
    @Bean
    public OpenAiStreamingChatModel openAiStreamingChatModel() {
        // 配置OpenAI Streaming Chat Model
        //流式调用
        OpenAiStreamingChatModel build = OpenAiStreamingChatModel.builder()
                .baseUrl(AIURL)
                .apiKey(AIKEY)
                .modelName("qwen-plus")
                .logRequests(true)
                .logResponses(true)
                .build();
        return build;
    }
    @Bean
    public ChatLanguageModel chatLanguageModel(){
        if (openAiStreamingChatModel()==null){
            return (ChatLanguageModel) OpenAiChatModel.builder()
                    .apiKey(AIKEY)
                    .modelName("qwen-plus")
                    .logRequests(true)
                    .logResponses(true)
                    .build();
        }else {
            return (ChatLanguageModel) openAiStreamingChatModel();
        }
        }


    //构建mcpTransport对象,用于调用mcp服务，和mcp服务器通信
    //连接的是百度地图MCP服务，可以配置多个mcpTransport对象,用于调用多个mcp服务，并实现负载均衡
    @Bean
    public McpTransport mcpTransport() {
        return  new HttpMcpTransport.Builder()
                .sseUrl("https://mcp.map.baidu.com/mcp?ak="+BAIDU_API_KEY) // 远程服务器的SSE端点地址
                .build();
    }
    //构建MCP客户端，指定连接方式
    @Bean
    public McpClient mcpClient1(McpTransport mcpTransport ){
        return new DefaultMcpClient.Builder()
                .transport(mcpTransport)
                .build();
    }
    //构建MCP工具提供者，用来发现tools方法并提供给AI
    @Bean
    public McpToolProvider toolProvider(McpClient mcpClient1, AiTools customTools){
        // 创建MCP工具提供者
        return McpToolProvider.builder()
                .mcpClients(List.of(mcpClient1))
                .build();
    }
    //    //配置ChatModel,对话记录
//    @Bean
//    public ChatMemory chatMemory() {
//        return MessageWindowChatMemory.builder()
//                .maxMessages(20)//最大保存的会话记录数量
//                .build();
//    }
    //配置ChatMemoryProvider,对话记忆
    @Bean
    public ChatMemoryProvider chatMemoryProvider() {
        return new ChatMemoryProvider() {
            @Override
            public ChatMemory get(Object id) {
                return MessageWindowChatMemory.builder()
                        .id( id)
                        .maxMessages( 20)
                        .chatMemoryStore( redisChatMemoryStore)
                        .build();
            }
        };
    }
    //除了第一次创建向量数据库外,其他时候,直接从数据库中获取向量数据库对象,在第一次启动后，
    @Bean
    public EmbeddingStore store(){
        //1.加载文档进内存,将文件名改为自己的,除了第一次启动外,其他时候,直接从数据库中获取文档对象,在第一次启动后，将该行注释掉
        List<Document> documents = ClassPathDocumentLoader.loadDocuments("content");
        //2.构建一个EmbeddingStoreIngestor对象,完成文本数据切割,向量化, 存储
        EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
                .embeddingStore(redisEmbeddingStore)
                .build();
        ingestor.ingest(documents);
        return redisEmbeddingStore;
    }
    //构建检索对象，检索rag数据库对象
    @Bean
    public ContentRetriever contentRetriever(EmbeddingStore store){
        return EmbeddingStoreContentRetriever.builder()
                .embeddingStore(store)//设置向量数据库操作对象
                .minScore(0.5)//设置最小分数
                .maxResults(3)//设置最大片段数量
                .build();
    }

}
